OpenCores
URL https://opencores.org/ocsvn/scarm/scarm/trunk

Subversion Repositories scarm

[/] [scarm/] [trunk/] [src/] [scBooth.cpp] - Rev 10

Go to most recent revision | Compare with Previous | Blame | View Log

///////////////////////////////////////////////////////////////////////////////
// This program is free software; you can redistribute it and/or
// modify it 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.
//////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////              
//          
//  Original Author: Allen Tao Zhong,
//  University of Electronic Science and Technology in China
//  email: zhong@opencores.org
//  info   This is a SystemC ARM model,I "stole" some codes from 
//       "swarm" , author Michael Dales (michael@dcs.gla.ac.uk)
// scBooth.cpp: implementation of the scBooth class.
//
//////////////////////////////////////////////////////////////////////
 
#include "scBooth.h"
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
 
 
scBooth::~scBooth()
{
 
}
///////////////////////////////////////////////////////////////////////////////
// carry_save_adder_32 - 32 bit carry save adder (well, what did you expect?).
//
void scBooth::carry_save_adder_32(uint32_t a, uint32_t b, uint32_t cin, 
			 uint32_t *res, uint32_t *cout)
{
  uint32_t ps, t1, t2;
 
  ps = a ^ b;
  *res = ps ^ cin;
 
  t1 = b & ~ps;
  t2 = cin & ps;
  *cout = t1 | t2;
 
  /*fprintf(stdout, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 
    a, b, cin, *res, *cout); 
    fflush(stdout);*/
}
 
 
#define SHIFT_LEFT(_x,_y)  ((_y >= 32) ? 0 : _x << _y)
#define SHIFT_RIGHT(_x,_y) ((_y >= 32) ? 0 : _x >> _y)
#define SIGNED_SHIFT_RIGHT(_x,_y) ((_y >= 32) ? ((_x >> 31) * 0xFFFFFFFF) : ((int32_t)_x) >> _y)
 
///////////////////////////////////////////////////////////////////////////////
// booth_stage_one - Does a single round of booths multiply algorithm. Note
//                   this works on 64 bits.
//
void scBooth::booth_one_stage(uint32_t* part_sum_hi, uint32_t* part_sum_lo, 
		     uint32_t* part_carry_hi, uint32_t* part_carry_lo, 
		     uint32_t mult, uint32_t N, bool_t* carry,
		     uint32_t multiplier, bool_t bSign)
{
  uint32_t temp;
  uint32_t srt;
 
  temp = multiplier & 0x3;
  temp |= (*carry == 1) ? 4 : 0;
 
  switch (temp)
    {
    case 0:
      carry_save_adder_32(*part_sum_lo, 0, *part_carry_lo,
			  part_sum_lo, part_carry_lo);
      carry_save_adder_32(*part_sum_hi, 0, *part_carry_hi,
			  part_sum_hi, part_carry_hi);
      break;
    case 1:
      carry_save_adder_32(*part_sum_lo, SHIFT_LEFT(mult,(2 * N)), 
			  *part_carry_lo,
			  part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult,(32 - (2 * N))) :
	SIGNED_SHIFT_RIGHT(mult,(32 - (2 * N)));
      carry_save_adder_32(*part_sum_hi, srt, *part_carry_hi,
			  part_sum_hi, part_carry_hi);
      break;
    case 2:
      carry_save_adder_32(*part_sum_lo, ~(SHIFT_LEFT(mult,((2 * N) + 1))), 
			  (*part_carry_lo) | 0x1 , part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult,(32 - ((2 * N) + 1))) :
	SIGNED_SHIFT_RIGHT(mult,(32 - ((2 * N) + 1)));
      carry_save_adder_32(*part_sum_hi, ~(srt), 
			  *part_carry_hi, part_sum_hi, part_carry_hi);
      break;
    case 3:
      carry_save_adder_32(*part_sum_lo, ~(SHIFT_LEFT(mult, (2 * N))), 
			  (*part_carry_lo) | 0x1 , part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult, (32 - (2 * N))) : 
	SIGNED_SHIFT_RIGHT(mult, (32 - (2 * N)));
      carry_save_adder_32(*part_sum_hi, ~(srt), 
			  *part_carry_hi, part_sum_hi, part_carry_hi);
      break;
    case 4:
      carry_save_adder_32(*part_sum_lo, SHIFT_LEFT(mult, (2 * N)), 
			  *part_carry_lo,
			  part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult, (32 - (2 * N))) :
	SIGNED_SHIFT_RIGHT(mult, (32 - (2 * N)));
      carry_save_adder_32(*part_sum_hi, srt, 
			  *part_carry_hi,
			  part_sum_hi, part_carry_hi);
      break;
    case 5:
      carry_save_adder_32(*part_sum_lo, SHIFT_LEFT(mult, ((2 * N) + 1)), 
			  *part_carry_lo,
			  part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult, (32 - ((2 * N) + 1))) : 
	SIGNED_SHIFT_RIGHT(mult, (32 - ((2 * N) + 1)));
      carry_save_adder_32(*part_sum_hi, 
			  srt, 
			  *part_carry_hi, part_sum_hi, part_carry_hi);
      break;
    case 6:
      carry_save_adder_32(*part_sum_lo, ~(SHIFT_LEFT(mult,(2 * N))), 
			  (*part_carry_lo) | 0x1 , part_sum_lo, part_carry_lo);
      srt = bSign == 0 ? SHIFT_RIGHT(mult,(32 - (2 * N))) : 
	SIGNED_SHIFT_RIGHT(mult,(32 - (2 * N)));
      carry_save_adder_32(*part_sum_hi, 
			  ~(srt), 
			  *part_carry_hi, part_sum_hi, part_carry_hi);
      break;
    case 7:
      carry_save_adder_32(*part_sum_lo, 0, *part_carry_lo,
			  part_sum_lo, part_carry_lo);
      carry_save_adder_32(*part_sum_hi, 0, *part_carry_hi,
			  part_sum_hi, part_carry_hi);
      break;
    }
 
#if 0
  if (N < 15)
    *carry = (temp >> 1) & 0x1;
  else
    *carry = 0;
#else
    *carry = (temp >> 1) & 0x1;
#endif
}
 
 
///////////////////////////////////////////////////////////////////////////////
// four_stage_booth - Does four rounds of booths alg at once
//
void scBooth::four_stage_booth(uint32_t* part_sum_hi, uint32_t* part_sum_lo, 
		      uint32_t* part_carry_hi, uint32_t* part_carry_lo,
		      uint32_t mult, uint32_t N, bool_t* carry,
		      uint32_t* multiplier, bool_t bSign)
{
  for (int i = 0; i < 4; i++)
    {
      booth_one_stage(part_sum_hi, part_sum_lo, 
		      part_carry_hi, part_carry_lo,
		      mult, (N * 4) + i, 
		      carry, *multiplier, bSign);
 
      *part_carry_hi = (*part_carry_hi << 1) | (*part_carry_lo >> 31);
      *part_carry_lo = *part_carry_lo << 1;
      *multiplier = *multiplier >> 2;
    }
}
 
 
 
void scBooth::entry()
{
  out=a*b;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.