Add ability to write out Elements in a PCB file.

The main .pcb file contains elements, and basic PCB status.
Write out a .pcb file with stub Elements for each of the devices
in the design.

Rearrange the way the files are reported to the code generator
so that we can sensibly express where the output files are.
This commit is contained in:
Stephen Williams 2011-12-23 17:06:55 -05:00
parent 9075326bb7
commit a57ce2a709
6 changed files with 218 additions and 29 deletions

View File

@ -45,7 +45,7 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = pcb.o scope.o show_netlist.o
O = pcb.o scope.o show_netlist.o show_pcb.o
all: dep pcb.tgt

View File

@ -25,7 +25,6 @@
# include "version_tag.h"
# include "pcb_config.h"
# include <string.h>
# include <stdio.h>
# include "pcb_priv.h"
# include "ivl_target.h"
@ -53,18 +52,8 @@ int target_design(ivl_design_t des)
ivl_scope_t*root_scopes;
unsigned nroot;
unsigned idx;
FILE*fnet;
int rc = 0;
const char*path = ivl_design_flag(des, "-o");
if (path == 0) {
return -1;
}
fnet = fopen(path, "w");
if (fnet == 0) {
perror (path);
return -2;
}
const char*pcb_path = ivl_design_flag(des, "-o");
ivl_design_roots(des, &root_scopes, &nroot);
for (idx = 0 ; idx < nroot ; idx += 1) {
@ -75,9 +64,15 @@ int target_design(ivl_design_t des)
}
}
show_netlist(fnet);
assert(pcb_path);
show_pcb(pcb_path);
const char*net_path = ivl_design_flag(des, "netlist");
if (net_path != 0) {
printf("Send netlist to %s\n", net_path);
show_netlist(net_path);
}
fclose(fnet);
return rc;
}

View File

@ -22,11 +22,16 @@
# include <string>
# include <set>
# include <list>
# include <cstdio>
# include <map>
# include <ivl_target.h>
extern int scan_scope(ivl_scope_t scope);
/*
* This nexus_list is a list of all the nets that the scan_scope
* collects, wrapped up into a list. The show_netlist dumps that list
* as a netlist.
*/
struct nexus_data {
std::string name;
std::set<std::string> pins;
@ -34,6 +39,21 @@ struct nexus_data {
extern std::list<struct nexus_data*> nexus_list;
extern void show_netlist(FILE*fnet);
/*
* The element_list is a collection of all the elements that were
* located by the scope scan. The key is the refdes for the element,
* and the value is the element_data_t structure that describes that
* element.
*/
struct element_data_t {
std::string description;
std::string value;
};
extern std::map <std::string, element_data_t*> element_list;
extern void show_netlist(const char*net_path);
extern void show_pcb(const char*pcb_path);
#endif

View File

@ -18,15 +18,24 @@
*/
# include "pcb_priv.h"
# include <cstring>
# include <map>
# include <string>
# include <cassert>
using namespace std;
list<struct nexus_data*> nexus_list;
static void sheet_box(ivl_scope_t scope);
static void black_box(ivl_scope_t scope);
map <string, element_data_t*> element_list;
struct attr_value {
ivl_attribute_type_t type;
string str;
long num;
};
static void sheet_box(ivl_scope_t scope, const map<string,attr_value>&attrs);
static void black_box(ivl_scope_t scope, const map<string,attr_value>&attrs);
static string wire_name(ivl_signal_t sig);
@ -35,20 +44,42 @@ int scan_scope(ivl_scope_t scope)
int black_box_flag = 0;
int idx;
map<string,attr_value> attrs;
// Scan the attributes, looking in particular for the
// black_box attribute.
// black_box attribute. While we are at it, save the collected
// attributes into a map that we can pass on to the processing
// functions.
for (idx = 0 ; idx < ivl_scope_attr_cnt(scope) ; idx += 1) {
ivl_attribute_t attr = ivl_scope_attr_val(scope, idx);
if (strcmp(attr->key, "ivl_black_box") == 0)
string attr_key = attr->key;
if (attr_key == "ivl_black_box") {
// Ah hah, this is a black box.
black_box_flag = 1;
} else {
struct attr_value val;
val.type = attr->type;
switch (val.type) {
case IVL_ATT_VOID:
break;
case IVL_ATT_STR:
val.str = attr->val.str;
break;
case IVL_ATT_NUM:
val.num = attr->val.num;
break;
}
attrs[attr_key] = val;
}
}
// If this scope is a black box, then process it
// so. Otherwise, process it as a sheet, which will recurse.
if (black_box_flag) {
black_box(scope);
black_box(scope, attrs);
} else {
sheet_box(scope);
sheet_box(scope, attrs);
}
return 0;
@ -60,7 +91,7 @@ static int child_scan_fun(ivl_scope_t scope, void*)
return 0;
}
void sheet_box(ivl_scope_t scope)
void sheet_box(ivl_scope_t scope, const map<string,attr_value>&attrs)
{
printf("Sheet %s...\n", ivl_scope_name(scope));
unsigned sigs = ivl_scope_sigs(scope);
@ -88,12 +119,76 @@ void sheet_box(ivl_scope_t scope)
* A black box is a component. Do not process the contents, other then
* to get at the ports that we'll attach to the netlist.
*/
static void black_box(ivl_scope_t scope)
static void black_box(ivl_scope_t scope, const map<string,attr_value>&attrs)
{
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
printf(" Component %s is %s\n", ivl_scope_name(scope), ivl_scope_tname(scope));
unsigned sigs = ivl_scope_sigs(scope);
// The refdes for the object is by default the name of
// the instance. If the user attaches a refdes
// attribute, then use that instead.
string refdes = ivl_scope_basename(scope);
map<string,attr_value>::const_iterator aptr = attrs.find("refdes");
if (aptr != attrs.end()) {
assert(aptr->second.type == IVL_ATT_STR);
refdes = aptr->second.str;
}
element_data_t*elem_data = new element_data_t;
// Scan the parameters of the module for any values that may
// be of interest to the PCB element.
unsigned params = ivl_scope_params(scope);
for (unsigned idx = 0 ; idx < params ; idx += 1) {
ivl_parameter_t par = ivl_scope_param(scope, idx);
string name = ivl_parameter_basename(par);
if (name == "description") {
ivl_expr_t exp = ivl_parameter_expr(par);
switch (ivl_expr_type(exp)) {
case IVL_EX_STRING:
elem_data->description = ivl_expr_string(exp);
break;
default:
assert(0);
}
} else if (name == "value") {
ivl_expr_t exp = ivl_parameter_expr(par);
switch (ivl_expr_type(exp)) {
case IVL_EX_STRING:
elem_data->value = ivl_expr_string(exp);
break;
default:
assert(0);
}
}
}
// If there is a "description" attribute for the device, then
// use that in place of the parameter.
if ( (aptr = attrs.find("description")) != attrs.end() ) {
assert(aptr->second.type == IVL_ATT_STR);
elem_data->description = aptr->second.str;
}
// Get the "value" attribute for the device.
if ( (aptr = attrs.find("value")) != attrs.end() ) {
switch (aptr->second.type) {
case IVL_ATT_VOID:
break;
case IVL_ATT_STR:
elem_data->value = aptr->second.str;
break;
case IVL_ATT_NUM:
assert(0);
break;
}
}
// Look for the ports of the black box and make sure they are
// attached to signals. Attach the port as a pin wired to a net.
unsigned sigs = ivl_scope_sigs(scope);
for (unsigned idx = 0 ; idx < sigs ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(scope, idx);
ivl_signal_port_t sip = ivl_signal_port(sig);
@ -106,12 +201,15 @@ static void black_box(ivl_scope_t scope)
struct nexus_data*nex_data = reinterpret_cast<struct nexus_data*>(ivl_nexus_get_private(nex));
assert(nex_data);
string refdes = ivl_scope_basename(scope);
string pindes = ivl_signal_basename(sig);
string pin = refdes + "-" + pindes;
nex_data->pins.insert(pin);
printf(" port %s\n", ivl_signal_basename(sig));
}
element_data_t*&eptr = element_list[refdes];
assert(eptr == 0);
eptr = elem_data;
}
static string wire_name(ivl_signal_t sig)

View File

@ -18,11 +18,19 @@
*/
# include "pcb_priv.h"
# include <cstdio>
using namespace std;
void show_netlist(FILE*fnet)
void show_netlist(const char*net_path)
{
assert(net_path);
FILE*fnet = fopen(net_path, "w");
if (fnet == 0) {
perror(net_path);
return;
}
for (list<nexus_data*>::iterator cur = nexus_list.begin()
; cur != nexus_list.end() ; ++ cur) {
@ -34,4 +42,6 @@ void show_netlist(FILE*fnet)
}
fprintf(fnet, "\n");
}
fclose(fnet);
}

66
tgt-pcb/show_pcb.cc Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "pcb_config.h"
# include "pcb_priv.h"
using namespace std;
static void show_pcb_header(FILE*fpcb)
{
fprintf(fpcb, "PCB[\"\" 400000 220000]\n");
fprintf(fpcb, "Grid[100.0 0 0 1]\n");
}
void show_pcb(const char*pcb_path)
{
assert(pcb_path);
FILE*fpcb = fopen(pcb_path, "w");
if (fpcb == 0) {
perror(pcb_path);
return;
}
show_pcb_header(fpcb);
// Draw the collected elements
for (map<string,element_data_t*>::const_iterator cur = element_list.begin()
; cur != element_list.end() ; ++ cur) {
const string&refdes = cur->first;
const string&descr = cur->second->description;
const string&value = cur->second->value;
fprintf(fpcb, "Element[\"\" \"%s\" \"%s\" \"%s\"",
descr.c_str(), refdes.c_str(), value.c_str());
// Mark-X Mark-Y
fprintf(fpcb, " 0 0");
// Text-X Text-Y text-direction Text-scale Text-flags
fprintf(fpcb, " 0 0 0 100 \"\"");
fprintf(fpcb, "]\n");
// Fill in the contents of the element. Should get this
// from a library.
fprintf(fpcb, "(\n");
fprintf(fpcb, ")\n");
}
fclose(fpcb);
}