From a57ce2a709c71205094965622b43dc8aaefc0717 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 23 Dec 2011 17:06:55 -0500 Subject: [PATCH] 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. --- tgt-pcb/Makefile.in | 2 +- tgt-pcb/pcb.cc | 23 +++----- tgt-pcb/pcb_priv.h | 24 +++++++- tgt-pcb/scope.cc | 120 ++++++++++++++++++++++++++++++++++++---- tgt-pcb/show_netlist.cc | 12 +++- tgt-pcb/show_pcb.cc | 66 ++++++++++++++++++++++ 6 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 tgt-pcb/show_pcb.cc diff --git a/tgt-pcb/Makefile.in b/tgt-pcb/Makefile.in index 328d7cf5a..9e728681a 100644 --- a/tgt-pcb/Makefile.in +++ b/tgt-pcb/Makefile.in @@ -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 diff --git a/tgt-pcb/pcb.cc b/tgt-pcb/pcb.cc index 7ac2e3c66..547dc3a7b 100644 --- a/tgt-pcb/pcb.cc +++ b/tgt-pcb/pcb.cc @@ -25,7 +25,6 @@ # include "version_tag.h" # include "pcb_config.h" # include -# include # 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; } diff --git a/tgt-pcb/pcb_priv.h b/tgt-pcb/pcb_priv.h index 8ff7a12d8..b98fceef0 100644 --- a/tgt-pcb/pcb_priv.h +++ b/tgt-pcb/pcb_priv.h @@ -22,11 +22,16 @@ # include # include # include -# include +# include # include 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 pins; @@ -34,6 +39,21 @@ struct nexus_data { extern std::list 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 element_list; + +extern void show_netlist(const char*net_path); + +extern void show_pcb(const char*pcb_path); #endif diff --git a/tgt-pcb/scope.cc b/tgt-pcb/scope.cc index 66ee706a2..22f8e25d4 100644 --- a/tgt-pcb/scope.cc +++ b/tgt-pcb/scope.cc @@ -18,15 +18,24 @@ */ # include "pcb_priv.h" -# include +# include +# include # include using namespace std; list nexus_list; -static void sheet_box(ivl_scope_t scope); -static void black_box(ivl_scope_t scope); +map element_list; + +struct attr_value { + ivl_attribute_type_t type; + string str; + long num; +}; + +static void sheet_box(ivl_scope_t scope, const map&attrs); +static void black_box(ivl_scope_t scope, const map&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 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&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&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::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(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) diff --git a/tgt-pcb/show_netlist.cc b/tgt-pcb/show_netlist.cc index a64445663..a2a5d6be2 100644 --- a/tgt-pcb/show_netlist.cc +++ b/tgt-pcb/show_netlist.cc @@ -18,11 +18,19 @@ */ # include "pcb_priv.h" +# include 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::iterator cur = nexus_list.begin() ; cur != nexus_list.end() ; ++ cur) { @@ -34,4 +42,6 @@ void show_netlist(FILE*fnet) } fprintf(fnet, "\n"); } + + fclose(fnet); } diff --git a/tgt-pcb/show_pcb.cc b/tgt-pcb/show_pcb.cc new file mode 100644 index 000000000..02623bb90 --- /dev/null +++ b/tgt-pcb/show_pcb.cc @@ -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::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); +}