Bring switch information out to the ivl_target API.
This involves defining the API for switches and cleaning up the elaborated form to match the defined ivl_target API. Also add t-dll code to support the ivl_switch_t functions, and add stub code that checks the results.
This commit is contained in:
parent
88313670c0
commit
ca756f3ec3
|
|
@ -88,6 +88,31 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
|
|||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, ivl_switch_type_t val)
|
||||
{
|
||||
switch (val) {
|
||||
case IVL_SW_TRAN:
|
||||
o << "tran";
|
||||
break;
|
||||
case IVL_SW_TRANIF0:
|
||||
o << "tranif0";
|
||||
break;
|
||||
case IVL_SW_TRANIF1:
|
||||
o << "tranif1";
|
||||
break;
|
||||
case IVL_SW_RTRAN:
|
||||
o << "rtran";
|
||||
break;
|
||||
case IVL_SW_RTRANIF0:
|
||||
o << "rtranif0";
|
||||
break;
|
||||
case IVL_SW_RTRANIF1:
|
||||
o << "rtranif1";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void dump_scope_path(ostream&o, const NetScope*scope)
|
||||
{
|
||||
if (const NetScope*parent = scope->parent()) {
|
||||
|
|
@ -613,11 +638,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetTran::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
const char*r = resistive_? "r" : "";
|
||||
const char*ifx = enable_==0? "" : enable_>0? "if1" : "if0";
|
||||
|
||||
o << setw(ind) << "" << r << "tran" << ifx << " " << name() << endl;
|
||||
|
||||
o << setw(ind) << "" << type_ << " " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
|
|||
12
elaborate.cc
12
elaborate.cc
|
|
@ -666,7 +666,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, false, 0);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRAN);
|
||||
}
|
||||
break;
|
||||
case RTRAN:
|
||||
|
|
@ -676,7 +676,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, true, 0);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRAN);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
|
@ -687,7 +687,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, false, -1);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF0);
|
||||
}
|
||||
break;
|
||||
case RTRANIF0:
|
||||
|
|
@ -697,7 +697,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, true, -1);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF0);
|
||||
}
|
||||
break;
|
||||
case TRANIF1:
|
||||
|
|
@ -707,7 +707,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, false, 1);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF1);
|
||||
}
|
||||
break;
|
||||
case RTRANIF1:
|
||||
|
|
@ -717,7 +717,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, true, 1);
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
11
ivl.def
11
ivl.def
|
|
@ -152,6 +152,8 @@ ivl_scope_port
|
|||
ivl_scope_ports
|
||||
ivl_scope_sigs
|
||||
ivl_scope_sig
|
||||
ivl_scope_switch
|
||||
ivl_scope_switches
|
||||
ivl_scope_time_precision
|
||||
ivl_scope_time_units
|
||||
ivl_scope_type
|
||||
|
|
@ -216,6 +218,15 @@ ivl_stmt_parm_count
|
|||
ivl_stmt_rval
|
||||
ivl_stmt_sub_stmt
|
||||
|
||||
ivl_switch_a
|
||||
ivl_switch_b
|
||||
ivl_switch_basename
|
||||
ivl_switch_enable
|
||||
ivl_switch_scope
|
||||
ivl_switch_type
|
||||
ivl_switch_attr_cnt;
|
||||
ivl_switch_attr_val;
|
||||
|
||||
ivl_udp_init
|
||||
ivl_udp_name
|
||||
ivl_udp_nin
|
||||
|
|
|
|||
52
ivl_target.h
52
ivl_target.h
|
|
@ -123,6 +123,9 @@ _BEGIN_DECL
|
|||
* ivl_process_t object holds one of these, but a statement may in
|
||||
* turn contain other statements.
|
||||
*
|
||||
* ivl_switch_t
|
||||
* Switches are the tran/tranif devices in the design.
|
||||
*
|
||||
* -- A Note About Bit Sets --
|
||||
* Some objects hold a value as an array of bits. In these cases there
|
||||
* is some method that retrieves the width of the value and another
|
||||
|
|
@ -155,6 +158,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
|
|||
typedef struct ivl_process_s *ivl_process_t;
|
||||
typedef struct ivl_scope_s *ivl_scope_t;
|
||||
typedef struct ivl_signal_s *ivl_signal_t;
|
||||
typedef struct ivl_switch_s *ivl_switch_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
|
||||
typedef struct ivl_statement_s*ivl_statement_t;
|
||||
|
||||
|
|
@ -226,6 +230,16 @@ typedef enum ivl_logic_e {
|
|||
IVL_LO_UDP = 21
|
||||
} ivl_logic_t;
|
||||
|
||||
/* This is the type of a ivl_switch_t object */
|
||||
typedef enum ivl_switch_type_e {
|
||||
IVL_SW_TRAN = 0,
|
||||
IVL_SW_TRANIF0 = 1,
|
||||
IVL_SW_TRANIF1 = 2,
|
||||
IVL_SW_RTRAN = 3,
|
||||
IVL_SW_RTRANIF0 = 4,
|
||||
IVL_SW_RTRANIF1 = 5
|
||||
} ivl_switch_type_t;
|
||||
|
||||
/* This is the type of an LPM object. */
|
||||
typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ABS = 32,
|
||||
|
|
@ -1501,6 +1515,8 @@ extern unsigned ivl_scope_ports(ivl_scope_t net);
|
|||
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_sigs(ivl_scope_t net);
|
||||
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_switches(ivl_scope_t net);
|
||||
extern ivl_switch_t ivl_scope_switch(ivl_scope_t net, unsigned idx);
|
||||
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
|
||||
extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
extern int ivl_scope_time_precision(ivl_scope_t net);
|
||||
|
|
@ -1826,6 +1842,42 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
|
|||
IVL_ST_WAIT, IVL_ST_WHILE */
|
||||
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
|
||||
|
||||
/* SWITCHES
|
||||
*
|
||||
* The switches represent the tran devices in the design.
|
||||
*
|
||||
* FUNCTION SUMMARY
|
||||
*
|
||||
* ivl_switch_type
|
||||
* Return the enumerated value that is the type of the switch.
|
||||
*
|
||||
* ivl_switch_basename
|
||||
* This is the name given to the device in the source code.
|
||||
*
|
||||
* ivl_switch_scope
|
||||
* The scope where the switch device appears.
|
||||
*
|
||||
* ivl_switch_a
|
||||
* ivl_switch_b
|
||||
* The a and b ports are the two ports of the switch.
|
||||
*
|
||||
* ivl_switch_enable
|
||||
* If the device has an enable (tranifX) then this is the enable
|
||||
* port.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
* The a/b ports can be any type, but the types must exactly
|
||||
* match. The enable must be a scalar.
|
||||
*/
|
||||
extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net);
|
||||
extern const char*ivl_switch_basename(ivl_switch_t net);
|
||||
extern ivl_scope_t ivl_switch_scope(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_a(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_b(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net);
|
||||
|
||||
extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);
|
||||
extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
|
||||
|
||||
#if defined(__MINGW32__) || defined (__CYGWIN32__)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
|
|
|
|||
19
net_tran.cc
19
net_tran.cc
|
|
@ -28,12 +28,25 @@
|
|||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, bool resistive, int enable)
|
||||
: NetNode(scope, n, enable? 3 : 2)
|
||||
static bool has_enable(ivl_switch_type_t tt)
|
||||
{
|
||||
switch (tt) {
|
||||
case IVL_SW_TRANIF0:
|
||||
case IVL_SW_TRANIF1:
|
||||
case IVL_SW_RTRANIF0:
|
||||
case IVL_SW_RTRANIF1:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
|
||||
: NetNode(scope, n, has_enable(tt)? 3 : 2)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
|
||||
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
|
||||
if (enable) {
|
||||
if (pin_count() == 3) {
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("E"), 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1362,15 +1362,16 @@ class NetSysFunc : public NetNode {
|
|||
class NetTran : public NetNode {
|
||||
|
||||
public:
|
||||
NetTran(NetScope*scope, perm_string n, bool resistive, int enable);
|
||||
NetTran(NetScope*scope, perm_string n, ivl_switch_type_t type);
|
||||
~NetTran();
|
||||
|
||||
ivl_switch_type_t type() const { return type_; }
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
bool resistive_;
|
||||
bool enable_;
|
||||
ivl_switch_type_t type_;
|
||||
};
|
||||
|
||||
/* =========
|
||||
|
|
|
|||
38
t-dll-api.cc
38
t-dll-api.cc
|
|
@ -1627,6 +1627,19 @@ extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
|
|||
return net->sigs_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_switches(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->switches.size();
|
||||
}
|
||||
|
||||
extern "C" ivl_switch_t ivl_scope_switch(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->switches.size());
|
||||
return net->switches[idx];
|
||||
}
|
||||
|
||||
extern "C" int ivl_scope_time_precision(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -2143,3 +2156,28 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" const char*ivl_switch_basename(ivl_switch_t net)
|
||||
{
|
||||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" ivl_switch_type_t ivl_switch_type(ivl_switch_t net)
|
||||
{
|
||||
return net->type;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_switch_a(ivl_switch_t net)
|
||||
{
|
||||
return net->pins[0];
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_switch_b(ivl_switch_t net)
|
||||
{
|
||||
return net->pins[1];
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_switch_enable(ivl_switch_t net)
|
||||
{
|
||||
return net->pins[2];
|
||||
}
|
||||
|
|
|
|||
60
t-dll.cc
60
t-dll.cc
|
|
@ -380,6 +380,19 @@ static void nexus_lpm_add(ivl_nexus_t nex, ivl_lpm_t net, unsigned pin,
|
|||
nex->ptrs_[top-1].l.lpm= net;
|
||||
}
|
||||
|
||||
static void nexus_switch_add(ivl_nexus_t nex, ivl_switch_t net, unsigned pin)
|
||||
{
|
||||
unsigned top = nex->nptr_ + 1;
|
||||
nex->ptrs_ = (struct ivl_nexus_ptr_s*)
|
||||
realloc(nex->ptrs_, top*sizeof(struct ivl_nexus_ptr_s));
|
||||
nex->nptr_ = top;
|
||||
|
||||
nex->ptrs_[top-1].type_= __NEXUS_PTR_SWI;
|
||||
nex->ptrs_[top-1].drive0 = IVL_DR_HiZ;
|
||||
nex->ptrs_[top-1].drive1 = IVL_DR_HiZ;
|
||||
nex->ptrs_[top-1].pin_ = pin;
|
||||
nex->ptrs_[top-1].l.swi= net;
|
||||
}
|
||||
|
||||
void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net)
|
||||
{
|
||||
|
|
@ -431,6 +444,11 @@ static void scope_add_lpm(ivl_scope_t scope, ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
static void scope_add_switch(ivl_scope_t scope, ivl_switch_t net)
|
||||
{
|
||||
scope->switches.push_back(net);
|
||||
}
|
||||
|
||||
ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
||||
const char*name)
|
||||
{
|
||||
|
|
@ -621,6 +639,13 @@ int dll_target::end_design(const Design*)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void dll_target::switch_attributes(struct ivl_switch_s *obj,
|
||||
const NetNode*net)
|
||||
{
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
}
|
||||
|
||||
void dll_target::logic_attributes(struct ivl_net_logic_s *obj,
|
||||
const NetNode*net)
|
||||
{
|
||||
|
|
@ -1010,9 +1035,38 @@ void dll_target::logic(const NetLogic*net)
|
|||
|
||||
bool dll_target::tran(const NetTran*net)
|
||||
{
|
||||
cerr << net->get_fileline() << ": sorry: "
|
||||
<< "trans devices not supported." << endl;
|
||||
return false;
|
||||
struct ivl_switch_s*obj = new struct ivl_switch_s;
|
||||
obj->type = net->type();
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins[0] = nex->t_cookie();
|
||||
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins[1] = nex->t_cookie();
|
||||
|
||||
nexus_switch_add(obj->pins[0], obj, 0);
|
||||
nexus_switch_add(obj->pins[1], obj, 1);
|
||||
|
||||
if (net->pin_count() > 2) {
|
||||
nex = net->pin(2).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins[2] = nex->t_cookie();
|
||||
nexus_switch_add(obj->pins[2], obj, 2);
|
||||
} else {
|
||||
obj->pins[2] = 0;
|
||||
}
|
||||
|
||||
switch_attributes(obj, net);
|
||||
scope_add_switch(obj->scope, obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dll_target::sign_extend(const NetSignExtend*net)
|
||||
|
|
|
|||
25
t-dll.h
25
t-dll.h
|
|
@ -23,6 +23,7 @@
|
|||
# include "ivl_target.h"
|
||||
# include "StringHeap.h"
|
||||
# include "netlist.h"
|
||||
# include <vector>
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#include <windows.h>
|
||||
|
|
@ -147,6 +148,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
ivl_scope_t lookup_scope_(const NetScope*scope);
|
||||
|
||||
ivl_attribute_s* fill_in_attributes(const Attrib*net);
|
||||
void switch_attributes(struct ivl_switch_s *obj, const NetNode*net);
|
||||
void logic_attributes(struct ivl_net_logic_s *obj, const NetNode*net);
|
||||
|
||||
private:
|
||||
|
|
@ -446,6 +448,19 @@ struct ivl_net_logic_s {
|
|||
ivl_expr_t delay[3];
|
||||
};
|
||||
|
||||
struct ivl_switch_s {
|
||||
ivl_switch_type_t type;
|
||||
|
||||
perm_string name;
|
||||
ivl_scope_t scope;
|
||||
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
|
||||
ivl_nexus_t pins[3];
|
||||
perm_string file;
|
||||
unsigned lineno;
|
||||
};
|
||||
|
||||
/*
|
||||
* UDP definition.
|
||||
|
|
@ -482,12 +497,14 @@ struct ivl_nexus_ptr_s {
|
|||
ivl_net_logic_t log; /* type 1 */
|
||||
ivl_net_const_t con; /* type 2 */
|
||||
ivl_lpm_t lpm; /* type 3 */
|
||||
ivl_switch_t swi; /* type 4 */
|
||||
} l;
|
||||
};
|
||||
# define __NEXUS_PTR_SIG 0
|
||||
# define __NEXUS_PTR_LOG 1
|
||||
# define __NEXUS_PTR_CON 2
|
||||
# define __NEXUS_PTR_LPM 3
|
||||
# define __NEXUS_PTR_SWI 4
|
||||
|
||||
/*
|
||||
* NOTE: ONLY allocate ivl_nexus_s objects with the included "new" operator.
|
||||
|
|
@ -568,6 +585,8 @@ struct ivl_scope_s {
|
|||
unsigned ports;
|
||||
ivl_signal_t*port;
|
||||
|
||||
std::vector<ivl_switch_t>switches;
|
||||
|
||||
signed int time_precision :8;
|
||||
signed int time_units :8;
|
||||
|
||||
|
|
@ -731,4 +750,10 @@ static inline void FILE_NAME(ivl_scope_t scope, const NetScope*info)
|
|||
scope->def_lineno = info->get_def_lineno();
|
||||
}
|
||||
|
||||
static inline void FILE_NAME(ivl_switch_t net, const LineInfo*info)
|
||||
{
|
||||
net->file = info->get_file();
|
||||
net->lineno = info->get_lineno();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ dep:
|
|||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = stub.o expression.o statement.o
|
||||
O = stub.o expression.o statement.o switches.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
|
|
|||
|
|
@ -35,6 +35,15 @@ extern FILE*out;
|
|||
*/
|
||||
extern int stub_errors;
|
||||
|
||||
/*
|
||||
* This function finds the vector width of a signal. It relies on the
|
||||
* assumption that all the signal inputs to the nexus have the same
|
||||
* width. The ivl_target API should assert that condition.
|
||||
*/
|
||||
extern unsigned width_of_nexus(ivl_nexus_t nex);
|
||||
|
||||
extern ivl_variable_type_t type_of_nexus(ivl_nexus_t nex);
|
||||
|
||||
/*
|
||||
* Show the details of the expression.
|
||||
*/
|
||||
|
|
@ -45,6 +54,8 @@ extern void show_expression(ivl_expr_t net, unsigned ind);
|
|||
*/
|
||||
extern void show_statement(ivl_statement_t net, unsigned ind);
|
||||
|
||||
extern void show_switch(ivl_switch_t net);
|
||||
|
||||
/*
|
||||
*/
|
||||
extern const char*data_type_string(ivl_variable_type_t vtype);
|
||||
|
|
|
|||
|
|
@ -1478,6 +1478,9 @@ static int show_scope(ivl_scope_t net, void*x)
|
|||
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1)
|
||||
show_lpm(ivl_scope_lpm(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_switches(net) ; idx += 1)
|
||||
show_switch(ivl_scope_switch(net, idx));
|
||||
|
||||
switch (ivl_scope_type(net)) {
|
||||
case IVL_SCT_FUNCTION:
|
||||
case IVL_SCT_TASK:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2008 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 "config.h"
|
||||
# include "priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <inttypes.h>
|
||||
# include <assert.h>
|
||||
|
||||
void show_switch(ivl_switch_t net)
|
||||
{
|
||||
const char*name = ivl_switch_basename(net);
|
||||
int has_enable = 0;
|
||||
|
||||
switch (ivl_switch_type(net)) {
|
||||
case IVL_SW_TRAN:
|
||||
fprintf(out, " tran %s", name);
|
||||
break;
|
||||
case IVL_SW_RTRAN:
|
||||
fprintf(out, " rtran %s", name);
|
||||
break;
|
||||
case IVL_SW_TRANIF0:
|
||||
fprintf(out, " tranif0 %s", name);
|
||||
has_enable = 1;
|
||||
break;
|
||||
case IVL_SW_RTRANIF0:
|
||||
fprintf(out, " rtranif0 %s", name);
|
||||
has_enable = 1;
|
||||
break;
|
||||
case IVL_SW_TRANIF1:
|
||||
fprintf(out, " tranif1 %s", name);
|
||||
has_enable = 1;
|
||||
break;
|
||||
case IVL_SW_RTRANIF1:
|
||||
fprintf(out, " rtranif1 %s", name);
|
||||
has_enable = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
|
||||
ivl_nexus_t nex = ivl_switch_a(net);
|
||||
const char*nex_name = nex? ivl_nexus_name(nex) : "";
|
||||
ivl_variable_type_t nex_type_a = nex? type_of_nexus(nex) : IVL_VT_NO_TYPE;
|
||||
fprintf(out, " A: %s <type=%s>\n", nex_name, data_type_string(nex_type_a));
|
||||
|
||||
nex = ivl_switch_b(net);
|
||||
nex_name = nex? ivl_nexus_name(nex) : "";
|
||||
ivl_variable_type_t nex_type_b = nex? type_of_nexus(nex) : IVL_VT_NO_TYPE;
|
||||
fprintf(out, " B: %s <type=%s>\n", nex_name, data_type_string(nex_type_b));
|
||||
|
||||
/* The A/B pins of the switch must be present, and must match. */
|
||||
if (nex_type_a == IVL_VT_NO_TYPE) {
|
||||
fprintf(out, " A: ERROR: Type missing for pin A\n");
|
||||
stub_errors += 1;
|
||||
}
|
||||
if (nex_type_b == IVL_VT_NO_TYPE) {
|
||||
fprintf(out, " B: ERROR: Type missing for pin B\n");
|
||||
stub_errors += 1;
|
||||
}
|
||||
if (nex_type_a != nex_type_b) {
|
||||
fprintf(out, " A/B: ERROR: Type mismatch between pins A and B\n");
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (has_enable) {
|
||||
nex = ivl_switch_enable(net);
|
||||
nex_name = nex? ivl_nexus_name(nex) : "";
|
||||
fprintf(out, " E: %s\n", nex_name);
|
||||
if (width_of_nexus(nex) != 1) {
|
||||
fprintf(out, " E: ERROR: Nexus width is %u\n",
|
||||
width_of_nexus(nex));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue