YosysHQ / arachne-pnr

Place and route tool for FPGAs
MIT License
414 stars 72 forks source link

std::out_of_range exception in src/global.cc:242 #81

Closed dpiegdon closed 6 years ago

dpiegdon commented 6 years ago

Given the latest toolchain (for exact tracking you can check out github.com/dpiegdon/IceStormToolchain.git) and the project in github.com/dpiegdon/orbuculum.git branch icestick-support in directory /orbtrace/, when typing make ICE40HX1K_STICK_EVN, yosys will fail with an std::out_of_range exception.

$> make ICE40HX1K_STICK_EVN
arachne-pnr -m 800 -d 1k -P tq144 -p toplevel_ice40hx1k_stick_evn.pcf traceIF.blif -o traceIF_ice40hx1k_stick_evn.txt
seed: 1
device: 1k
read_chipdb +/share/arachne-pnr/chipdb-1k.bin...
  supported packages: cb121, cb132, cb81, cm121, cm36, cm49, cm81, qn84, swg16tr, tq144, vq100
read_blif traceIF.blif...
prune...
read_pcf toplevel_ice40hx1k_stick_evn.pcf...
instantiate_io...
pack...

After packing:
IOs          20 / 96
GBs          0 / 8
  GB_IOs     1 / 8
LCs          942 / 1280
  DFF        286
  CARRY      188
  CARRY, DFF 4
  DFF PASS   84
  CARRY PASS 28
BRAMs        2 / 16
WARMBOOTs    0 / 1
PLLs         1 / 1

place_constraints...
promote_globals...
terminate called after throwing an instance of 'std::out_of_range'
  what():  map::at
gmake: *** [Makefile:27: build] Aborted

It is quite possible that the project is too big to be mappen on an HX1K. I am trying to port a project that can successfully be built using yosys et al for an HX8K to an HX1K (see given repo). That might be the actual source of the bug.

gdb backtrace:

#0  0x00007ffff7144e65 in raise () from /lib64/libc.so.6
#1  0x00007ffff7146b6a in abort () from /lib64/libc.so.6
#2  0x00007ffff7a92f1d in __gnu_cxx::__verbose_terminate_handler () at /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff7a90d46 in __cxxabiv1::__terminate (handler=) at /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:47
#4  0x00007ffff7a90d91 in std::terminate () at /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/libsupc++/eh_terminate.cc:57
#5  0x00007ffff7a90fa9 in __cxxabiv1::__cxa_throw (obj=obj@entry=0xa7ede0, tinfo=Reading in symbols for /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/libsupc++/tinfo.cc...done.
0x7ffff7dc9950 , dest=Reading in symbols for /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/src/c++98/stdexcept.cc...done.
0x7ffff7aa65a0 ) at /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/libsupc++/eh_throw.cc:87
#6  0x00007ffff7aba79f in std::__throw_out_of_range (__s=0x4c135d "map::at") at /var/tmp/portage/sys-devel/gcc-5.4.0-r3/work/gcc-5.4.0/libstdc++-v3/src/c++11/functexcept.cc:90
#7  0x0000000000457398 in std::map, std::allocator > >::at (this=0x72c028, __k=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5/bits/stl_map.h:532
#8  0x00000000004b2007 in Promoter::promote (this=0x7fffffff98c0, do_promote=true) at src/global.cc:242
#9  0x00000000004b3c33 in promote_globals (ds=..., do_promote=true) at src/global.cc:474
#10 0x000000000040708f in main (argc=12, argv=0x7fffffffda08) at src/arachne-pnr.cc:542

the actual line triggering the exception is in frame 8:

#8  0x00000000004b2007 in Promoter::promote (this=0x7fffffff98c0, do_promote=true) at src/global.cc:242
242                   int g = chipdb->loc_pin_glb_num.at(chipdb->cell_location[c]);

the problem seems to be that chipdb->cell_location[c] resolves to something that is not contained in chipdb->loc_pin_glb_num.

(gdb) print chipdb->cell_location[c]
Reading in symbols for src/chipdb.cc...done.
$2 = (__gnu_cxx::__alloc_traits >::value_type &) @0xb21588: {
  m_tile = 248,
  m_pos = 1
}
(gdb) print chipdb->loc_pin_glb_num
$3 = std::map with 8 elements = {
  [{
    m_tile = 6,
    m_pos = 1
  }] = 6,
  [{
    m_tile = 7,
    m_pos = 0
  }] = 3,
  [{
    m_tile = 112,
    m_pos = 1
  }] = 1,
  [{
    m_tile = 125,
    m_pos = 1
  }] = 0,
  [{
    m_tile = 126,
    m_pos = 0
  }] = 4,
  [{
    m_tile = 139,
    m_pos = 0
  }] = 5,
  [{
    m_tile = 244,
    m_pos = 1
  }] = 7,
  [{
    m_tile = 245,
    m_pos = 0
  }] = 2
}

I am unsure how to proceed here; I do not know very much about internals of FPGAs and cannot make too much sense of the code.

i would appreciate it if you helped me fix this issue.

mmicko commented 6 years ago

Ok I have done some research and here are findings.

In project icestorm there is generated file chipdb-1k.txt that contain list of GLOBAL_BUFFER_OUTPUTs

.gbufpin 13 8 1 0 0 8 1 1 7 17 0 2 7 0 0 3 0 9 0 4 13 9 0 5 6 0 1 6 6 17 1 7

If we check tile 248 (hex F8) we will find that it is tile : F8=10 + 14*17 , and that correspond to PIN 116 for tq144 ( 116 10 17 1 )

And we can see that value is not in gbufpin list, so it can not be used. If I map gbufpin this to pins I get list : 93,21,128,50 ,20 ,94 ,49 and 129 So those are the pins that should be used.

For 8K build pin H16 ( location 33 17 0) is used, and that one is also in gbufpin list for 8k, so that is reason why that is working.

My suggestion is just to add check if pin is contained in list, and if not give error back to user.

mmicko commented 6 years ago

Here is a patch I had on mind:

 src/global.cc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/global.cc b/src/global.cc
index bf5d00c..79d12ea 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -239,7 +239,10 @@ Promoter::promote(bool do_promote)
           Port *out = inst->find_port("GLOBAL_BUFFER_OUTPUT");
           if (out->connected())
             {
-              int g = chipdb->loc_pin_glb_num.at(chipdb->cell_location[c]);
+             auto loc = chipdb->cell_location[c];
+             if (chipdb->loc_pin_glb_num.find(loc) == chipdb->loc_pin_glb_num.end())
+                 fatal(fmt("Not able to use pin " << ds.package.loc_pin.at(loc) << " for global buffer output"));
+              int g = chipdb->loc_pin_glb_num.at(loc);
               for (uint8_t gc : global_classes)
                 {
                   if (gc & (1 << g))
dpiegdon commented 6 years ago

Thanks! That actually makes a lot of sense.

Sadly that means that the HX1K IceStick does not have a single GBIN pin on a header...

cliffordwolf commented 6 years ago

Sadly that means that the HX1K IceStick does not have a single GBIN pin on a header...

Yes. I've heard people complain about that before.. :)

But if you can afford the slight additional delay you can still route to the global net via the FPGA fabric. Use the SB_GB to do that. (But if its a clock then arachne-pnr will instantiate the SB_GB automatically for you in most cases.)

dpiegdon commented 6 years ago

Thanks for the hint! I think this is feasible here and I just implemented it :).

mmicko commented 6 years ago

@dpiegdon No problem, glad I could help. Was interesting to get more into this tool source and better understand Lattice internal organisation.