2000-12-09 04:42:52 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2000 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
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2000-12-09 04:42:52 +01:00
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
2001-02-07 23:21:59 +01:00
|
|
|
# include "ivl_target.h"
|
2000-12-09 04:42:52 +01:00
|
|
|
# include <stdio.h>
|
|
|
|
|
# include <assert.h>
|
|
|
|
|
# include "priv.h"
|
|
|
|
|
|
2000-12-09 06:40:42 +01:00
|
|
|
/*
|
|
|
|
|
* The fit_registers function scans all the scopes for flip-flop
|
|
|
|
|
* devices to be assigned to macrocells. First look to see if the
|
|
|
|
|
* device is connected to a PAD directly or through a bufif device. If
|
|
|
|
|
* not, then just pick a free macrocell and drop it there.
|
|
|
|
|
*/
|
|
|
|
|
|
2001-05-16 05:55:30 +02:00
|
|
|
static int scan_ff_q(ivl_lpm_t ff, unsigned q);
|
2000-12-09 04:42:52 +01:00
|
|
|
|
2001-01-15 01:05:39 +01:00
|
|
|
int fit_registers(ivl_scope_t scope, void*x)
|
2000-12-09 04:42:52 +01:00
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
unsigned idx;
|
|
|
|
|
unsigned lpms;
|
|
|
|
|
|
2000-12-09 06:40:42 +01:00
|
|
|
/* Scan child scopes first... */
|
2001-01-15 01:05:39 +01:00
|
|
|
rc = ivl_scope_children(scope, fit_registers, 0);
|
2000-12-09 04:42:52 +01:00
|
|
|
if (rc != 0)
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
|
|
|
2000-12-09 06:40:42 +01:00
|
|
|
/* Scan the current scope for flip-flop devices. Pass the
|
|
|
|
|
devices we find to the scan_ff_q function to assign to a
|
|
|
|
|
macrocell. */
|
|
|
|
|
|
|
|
|
|
lpms = ivl_scope_lpms(scope);
|
2000-12-09 04:42:52 +01:00
|
|
|
for (idx = 0 ; idx < lpms ; idx += 1) {
|
|
|
|
|
ivl_lpm_t lpm = ivl_scope_lpm(scope, idx);
|
|
|
|
|
unsigned wid, q;
|
|
|
|
|
|
|
|
|
|
if (ivl_lpm_type(lpm) != IVL_LPM_FF)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
wid = ivl_lpm_width(lpm);
|
|
|
|
|
|
|
|
|
|
for (q = 0 ; q < wid ; q += 1) {
|
2001-05-16 05:55:30 +02:00
|
|
|
rc = scan_ff_q(lpm, q);
|
2000-12-09 04:42:52 +01:00
|
|
|
if (rc != 0)
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-12-09 06:40:42 +01:00
|
|
|
/*
|
|
|
|
|
* This is the part that actually assigns the single bit of a single
|
|
|
|
|
* flip-flop to a single macrocell.
|
|
|
|
|
*/
|
2001-05-16 05:55:30 +02:00
|
|
|
int scan_ff_q(ivl_lpm_t ff, unsigned q)
|
2000-12-09 04:42:52 +01:00
|
|
|
{
|
|
|
|
|
unsigned idx;
|
|
|
|
|
ivl_nexus_t nex;
|
|
|
|
|
|
2001-05-16 05:55:30 +02:00
|
|
|
nex = ivl_lpm_q(ff, q);
|
2000-12-09 04:42:52 +01:00
|
|
|
|
|
|
|
|
/* First, look to see if the Q is already connected to a pin
|
|
|
|
|
or an enable. If I find such a connection, then immediately
|
|
|
|
|
finish. */
|
|
|
|
|
|
|
|
|
|
for (idx = 0 ; idx < pins ; idx += 1) {
|
|
|
|
|
struct pal_bind_s*pin = bind_pin + idx;
|
|
|
|
|
|
|
|
|
|
if (pin->sop == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pin->enable) {
|
|
|
|
|
|
|
|
|
|
if (nex == ivl_logic_pin(pin->enable, 1)) {
|
|
|
|
|
pin->reg = ff;
|
|
|
|
|
pin->reg_q = q;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (pin->nexus == nex) {
|
|
|
|
|
|
|
|
|
|
pin->reg = ff;
|
|
|
|
|
pin->reg_q = q;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-12-09 06:40:42 +01:00
|
|
|
/* There is no pin connection, so try setting this to an
|
2000-12-09 04:42:52 +01:00
|
|
|
unbound sop cell. We know that a sop is unbound if there
|
|
|
|
|
are no enables, nexus or ff devices connected to it. */
|
|
|
|
|
|
|
|
|
|
for (idx = 0 ; idx < pins ; idx += 1) {
|
|
|
|
|
struct pal_bind_s*pin = bind_pin + idx;
|
|
|
|
|
|
|
|
|
|
if (pin->sop == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pin->enable || pin->nexus || pin->reg)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Found one. Put the reg here. Leave the nexus empty so
|
|
|
|
|
that the code generator knows to disable the pin. */
|
|
|
|
|
pin->reg = ff;
|
|
|
|
|
pin->reg_q = q;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "No room for this ff.\n");
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|